package fiuba.algo3.XMLProcessor.EntradaSalida;


import fiuba.algo3.XMLProcessor.EntradaSalida.LectorTokens;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import fiuba.algo3.XMLProcessor.nucleo.Nodo;
import fiuba.algo3.XMLProcessor.nucleo.NodoAtributo;
import fiuba.algo3.XMLProcessor.nucleo.NodoTexto;
import fiuba.algo3.XMLProcessor.nucleo.NodoXML;

public class ParserXML
{
	LectorTokens lector;

	public ParserXML(String nombreArchivo) throws FileNotFoundException
	{
		lector = new LectorTokens(nombreArchivo);
	}

	public void cerrar()
	{
		lector.cerrar();
	}

	private NodoAtributo leerAtributo()
	{
		lector.saltearEspacios();
		String nombre = lector.leerIdentificador();
		if (nombre.isEmpty())
			return null;

		String valor = lector.leerContenidoEntreTokens('\"','\"',lector.NOINCLUSIVE);
		lector.saltearHasta('\"', lector.INCLUSIVE);

		return new NodoAtributo(nombre, valor);
	}

	private NodoTexto leerTexto()
	{
		lector.saltearEspacios();
		String texto = lector.leerHasta('<',lector.NOINCLUSIVE);
		if (texto.isEmpty())
			return null;
		return new NodoTexto(texto);
	}

	private List<NodoAtributo> leerListaAtributos()
	{
		List<NodoAtributo> listaAtributos = new ArrayList();
		NodoAtributo nodoAtributo = leerAtributo();
		while (nodoAtributo != null)
		{
			listaAtributos.add(nodoAtributo);
			nodoAtributo = leerAtributo();
		}

		return listaAtributos;
	}

	private Nodo leerNodo()
	{
		lector.saltearHasta('<', lector.INCLUSIVE);
		lector.saltearEspacios();
		if (lector.verUltimoCaracter() == '/')
		{
			return null;
		}
		String nombre = lector.leerIdentificador();
		if (nombre.isEmpty())
			return null;

		Nodo nodo = new Nodo(nombre);
		nodo.agregarAtributo(leerListaAtributos());

		lector.saltearEspacios();

		char caracter = lector.verUltimoCaracter();
		lector.saltearHasta('>',lector.INCLUSIVE);

		if (caracter == '/')
			return nodo;

		nodo.agregarNodo(leerListaNodos());

		lector.saltearHasta('>',lector.INCLUSIVE);
		return nodo;
	}

	private NodoXML leerProximoNodo()
	{
		NodoXML nodo = leerTexto();
		if (nodo != null)
			return nodo;
		return leerNodo();
	}

	private List<NodoXML> leerListaNodos()
	{
		List<NodoXML> listaNodos = new ArrayList();
		NodoXML nodo = leerProximoNodo();
		while (nodo != null)
		{
			listaNodos.add(nodo);
			nodo = leerProximoNodo();
		}

		return listaNodos;
	}

	public Nodo parsear()
	{
		Nodo nodo = leerNodo();
		if (nodo == null)
			{
				if (lector.verUltimoCaracter() != '?')
					return null;

				lector.saltearHasta('>', lector.INCLUSIVE);
				return parsear();
			}
		return nodo;
	}
}
